﻿using System;
using System.Web;
using System.Web.Caching;

namespace Southern.Common.Cache
{
    /// <summary>
    /// The cache resolver of type <see cref="System.Web.Caching.Cache"/>
    /// </summary>
	public class HttpRuntimeCacheResolver : ICache
    {
        private string keyPrefix = string.Empty;

        public HttpRuntimeCacheResolver() 
        { 
        }

        public HttpRuntimeCacheResolver(string cacheKeyPrefix) 
        {
            if(!string.IsNullOrEmpty(cacheKeyPrefix))
                this.keyPrefix = cacheKeyPrefix;
        }

        private string combindCacheKey(string key)
        {
            return this.keyPrefix + key;
        }

        #region ICache Members

        public void Add(string key, object value, TimeSpan timeout)
        {
            if (!this.Contains(key))
            {
                HttpRuntime.Cache.Add(
                    key,
                    value,
                    null,
                    System.Web.Caching.Cache.NoAbsoluteExpiration,
                    timeout,
                    System.Web.Caching.CacheItemPriority.Normal,
                    null);
            }
            else
            {
                HttpRuntime.Cache[key] = value;
            }
        }

        public virtual void Add(string key, object value)
        {
            HttpRuntime.Cache.Insert(this.combindCacheKey(key), value);
        }

		public void Add(string key, object value, CacheDependency dependency)
		{
            HttpRuntime.Cache.Insert(this.combindCacheKey(key), value, dependency);
		}

        public bool Contains(string key)
        {
            return HttpRuntime.Cache[this.combindCacheKey(key)] != null;
            //return false;
        }

        public void Flush()
        {
            
        }

        public object Get(string key)
        {
            return HttpRuntime.Cache[this.combindCacheKey(key)];
            //return null;
        }

        public void Remove(string key)
        {
            HttpRuntime.Cache.Remove(this.combindCacheKey(key));
        }

        public void Set(string key, object value, TimeSpan timeout)
        {
            HttpRuntime.Cache[this.combindCacheKey(key)] = value;
        }

        public void Set(string key, object value)
        {
            HttpRuntime.Cache[this.combindCacheKey(key)] = value;
        }

        #endregion
	}


	public class HttpSessionStateCacheResolver : ICache
    {
        private string keyPrefix = string.Empty;

        public HttpSessionStateCacheResolver() 
        { 
        }

        public HttpSessionStateCacheResolver(string cacheKeyPrefix) 
        {
            if(!string.IsNullOrEmpty(cacheKeyPrefix))
                this.keyPrefix = cacheKeyPrefix;
        }

        private string combindCacheKey(string key)
        {
            return this.keyPrefix + key;
        }

        #region ICacher Members

        public void Add(string key, object value)
        {
            //this.RegetSession();
            HttpContext.Current.Session.Add(this.combindCacheKey(key), value);
        }

		public void Add(string key, object value, CacheDependency dependency)
		{
			//this.RegetSession();
            HttpContext.Current.Session.Add(this.combindCacheKey(key), value);
		}

        public void Add(string key, object value, TimeSpan timeout)
        {
            //this.RegetSession();
            HttpContext.Current.Session.Add(this.combindCacheKey(key), value);
        }

        public bool Contains(string key)
        {
            //this.RegetSession();
            return HttpContext.Current.Session[this.combindCacheKey(key)] != null;
        }

        public void Flush()
        {
            //this.RegetSession();
            HttpContext.Current.Session.Abandon();
        }

        public object Get(string key)
        {
            //this.RegetSession();
            return HttpContext.Current.Session[this.combindCacheKey(key)];
        }

        public void Remove(string key)
        {
            //this.RegetSession();
            HttpContext.Current.Session.Remove(this.combindCacheKey(key));
        }

        public void Set(string key, object value)
        {
            if (this.Contains(this.combindCacheKey(key)))
            {
                //this.RegetSession();
                HttpContext.Current.Session[this.combindCacheKey(key)] = value;
            }
        }

        public void Set(string key, object value, TimeSpan timeout)
        {
            this.Set(this.combindCacheKey(key), value);
        }

        #endregion
    }

    /// <summary>
    /// The cache depend on HttpRequest by using <see cref="HttpContext.Current.Items"/>
    /// </summary>
    public class HttpRequestCacheResolver : ICache
    {
        private string keyPrefix = string.Empty;

        public HttpRequestCacheResolver() 
        { 
        }

        public HttpRequestCacheResolver(string cacheKeyPrefix) 
        {
            if(!string.IsNullOrEmpty(cacheKeyPrefix))
                this.keyPrefix = cacheKeyPrefix;
        }

        private string combindCacheKey(string key)
        {
            return this.keyPrefix + key;
        }

        #region ICacher Members

        public void Add(string key, object value)
        {
            HttpContext.Current.Items[this.combindCacheKey(key)] = value;
        }

        public void Add(string key, object value, TimeSpan timeout)
        {
            this.Add(this.combindCacheKey(key), value);
        }

    	public void Add(string key, object value, CacheDependency dependency)
    	{
            this.Add(this.combindCacheKey(key), value);
    	}

    	public bool Contains(string key)
        {
            return HttpContext.Current.Items[this.combindCacheKey(key)] != null;
        }

        public void Flush()
        {

        }

        public object Get(string key)
        {
            return HttpContext.Current.Items[this.combindCacheKey(key)];
        }

        public void Remove(string key)
        {
            HttpContext.Current.Items.Remove(this.combindCacheKey(key));
        }

        public void Set(string key, object value)
        {
            HttpContext.Current.Items[this.combindCacheKey(key)] = value;
        }

        public void Set(string key, object value, TimeSpan timeout)
        {
            this.Set(this.combindCacheKey(key), value);
        }
        #endregion
    }

    /// <summary>
    /// No cache class
    /// </summary>
    public class NoCacheResolver : ICache
    {
        #region ICache Members

        public void Add(string key, object value)
        {
            
        }

        public void Add(string key, object value, TimeSpan timeout)
        {
            
        }

        public void Add(string key, object value, CacheDependency dependency)
        {
            
        }

        public void Set(string key, object value)
        {
            
        }

        public void Set(string key, object value, TimeSpan timeout)
        {
            
        }

        public bool Contains(string key)
        {
            return false;
        }

        public void Flush()
        {
            
        }

        public object Get(string key)
        {
            return null;
        }

        public void Remove(string key)
        {
            
        }

        #endregion
    }
}
